/*
* Copyright (c) 2002-2015, JIDE Software Inc. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package jidefx.scene.control.field.popup;
import javafx.beans.property.ObjectProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Pos;
import javafx.scene.control.ChoiceBox;
import javafx.scene.control.ComboBox;
import javafx.scene.control.Label;
import javafx.scene.layout.Border;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.BorderStroke;
import javafx.scene.layout.BorderStrokeStyle;
import javafx.scene.layout.BorderWidths;
import javafx.scene.layout.CornerRadii;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.util.Callback;
import jidefx.scene.control.decoration.DecorationPane;
import jidefx.scene.control.field.NumberField;
import jidefx.scene.control.searchable.ComboBoxSearchable;
import jidefx.utils.FXUtils;
import jidefx.utils.FontUtils;
import jidefx.utils.LazyLoadUtils;
import net.miginfocom.layout.AC;
import net.miginfocom.layout.CC;
import net.miginfocom.layout.LC;
import org.tbee.javafx.scene.layout.MigPane;
import java.text.DecimalFormat;
import java.util.List;
import java.util.Locale;
/**
* The content of the Popup to edit a Font.
*/
public class FontPopupContent extends DecorationPane implements PopupContent<Font> {
private static final String STYLE_CLASS_DEFAULT = "popup-content"; //NON-NLS
private ComboBox<String> _fontFamilyComboBox;
private NumberField _sizeSpinner;
private ChoiceBox<String> _styleChoiceBox;
private Label _previewLabel;
public FontPopupContent(Font font) {
super(new MigPane(new LC().maxWidth("230px").maxHeight("180px").insets("10 10 10 10"), //NON-NLS
new AC().align("right", 0).size("160px", 1).fill(1).grow(1).gap("10px"), //NON-NLS
new AC().gap("6px"))); //NON-NLS
getStylesheets().add(PopupContent.class.getResource("PopupContent.css").toExternalForm()); //NON-NLS
getStyleClass().add(STYLE_CLASS_DEFAULT);
initializeComponents(font == null ? Font.getDefault() : font);
installListeners();
updateValues();
}
private void initializeComponents(Font font) {
// create components
BorderPane previewPanel = new BorderPane();
previewPanel.setBorder(new Border(new BorderStroke(Color.GRAY, BorderStrokeStyle.SOLID, CornerRadii.EMPTY, new BorderWidths(1))));
_previewLabel = new Label(getResourceString("preview"));
_previewLabel.setPrefSize(210, 60);
_previewLabel.setAlignment(Pos.CENTER);
_previewLabel.setFont(font);
previewPanel.setCenter(_previewLabel);
_fontFamilyComboBox = new ComboBox<>();
LazyLoadUtils.install(_fontFamilyComboBox, new Callback<ComboBox<String>, ObservableList<String>>() {
@Override
public ObservableList<String> call(ComboBox<String> comboBox) {
return FXCollections.observableArrayList(Font.getFamilies());
}
});
_fontFamilyComboBox.setPrefWidth(160); // Without setting it, it will come up with a small size then expand when setItems is called
new ComboBoxSearchable<>(_fontFamilyComboBox);
DecimalFormat integerFormat = (DecimalFormat) DecimalFormat.getNumberInstance();
integerFormat.setMaximumIntegerDigits(3);
integerFormat.setMaximumFractionDigits(1);
_sizeSpinner = new NumberField();
_sizeSpinner.setDecimalFormat(integerFormat);
_sizeSpinner.setSpinnersVisible(true);
_sizeSpinner.setValue(font.getSize());
_styleChoiceBox = new ChoiceBox<>();
// layout components
MigPane content = (MigPane) getContent();
content.add(previewPanel, new CC().grow().span(2).wrap().gapBottom("6px")); //NON-NLS
content.add(new Label(getResourceString("font")));
content.add(_fontFamilyComboBox, new CC().wrap());
Label sizeLabel = new Label(getResourceString("size"));
content.add(sizeLabel);
content.add(_sizeSpinner, new CC().split().maxWidth("60px").wrap()); //NON-NLS
_sizeSpinner.installAdjustmentMouseHandler(sizeLabel);
content.add(new Label(getResourceString("style")));
content.add(_styleChoiceBox, new CC().grow().wrap());
}
private void updateValues() {
Font font = getValue();
_fontFamilyComboBox.setValue(font.getFamily());
_styleChoiceBox.setValue(font.getStyle());
}
private void installListeners() {
_fontFamilyComboBox.valueProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
updateStyleChoiceBox();
}
});
_sizeSpinner.valueProperty().addListener(new ChangeListener<Number>() {
@Override
public void changed(ObservableValue<? extends Number> observable, Number oldValue, Number newValue) {
updateStyleChoiceBox();
}
});
_styleChoiceBox.valueProperty().addListener(new ChangeListener<String>() {
@Override
public void changed(ObservableValue<? extends String> observable, String oldValue, String newValue) {
_previewLabel.setFont(FontUtils.createFont(_fontFamilyComboBox.getValue(), newValue, _sizeSpinner.getValue().doubleValue()));
}
});
}
private void updateStyleChoiceBox() {
LazyLoadUtils.install(_styleChoiceBox, new Callback<ChoiceBox<String>, ObservableList<String>>() {
@Override
public ObservableList<String> call(final ChoiceBox<String> comboBox) {
final List<String> supportedFontStyle = FontUtils.getSupportedFontStyles(_fontFamilyComboBox.getValue(), _sizeSpinner.getValue().doubleValue());
FXUtils.runThreadSafe(new Runnable() {
@Override
public void run() {
comboBox.setDisable(supportedFontStyle.size() <= 1);
}
});
return FXCollections.observableArrayList(supportedFontStyle);
}
});
}
@Override
public final Font getValue() {
return _previewLabel.getFont();
}
@Override
public final void setValue(Font value) {
_previewLabel.setFont(value);
}
@Override
public final ObjectProperty<Font> valueProperty() {
return _previewLabel.fontProperty();
}
/**
* Gets the localized string from resource bundle. Subclass can override it to provide its own string. Available
* keys are defined in grid.properties that begins with "Filter." and lucene.properties that begins with "Lucene".
*
* @param key the key to the resource.
* @return the localized string.
*/
public String getResourceString(String key) {
if (key == null) {
return "";
}
return PopupsResource.getResourceBundle(Locale.getDefault()).getString(key);
}
}